package com.zhang.sequencegenerate.manager;

import com.zhang.sequencegenerate.entity.SequenceRecord;
import com.zhang.sequencegenerate.exception.BizException;
import com.zhang.sequencegenerate.service.SequenceRecordService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @Description 序列生成器
 * @Author Mr.Zhang
 * @Date 2025/5/25 19:04
 * @Version 1.0
 */
@Slf4j
@Component
public class SequenceManager {

    @Autowired
    private SequenceRecordService sequenceRecordService;


    @Data
    private class SequenceHolder {

        private String key;

        /**
         * 当前序列号,初始化是为 0
         */
        private AtomicLong sequenceValue;

        /**
         * 数据库保存的序列号
         */
        private long dbValue;

        /**
         * 步长，用来判断序列号是否还在给定的步长范围内
         */
        private long step;

        public SequenceHolder(long step) {
            this.step = step;
        }


        public long nextValue() {
            if (sequenceValue == null) {
                // 初始化
                this.init();
            }
            long sequence = sequenceValue.incrementAndGet();
            if (sequence > step) {
                // 意味着分配给它的序列号已经用完，需要重新分配
                this.nextRound();
                return this.nextValue();
            } else {
                return dbValue + sequence;
            }
        }

        private synchronized void nextRound() {
            if (sequenceValue.get() > step) {
                // 重新生成下一个序列号
                dbValue = SequenceManager.this.nextValue(key, step) - step;
                sequenceValue = new AtomicLong(0);
            }
        }

        private synchronized void init() {
            if (sequenceValue != null) {
                return;
            }
            dbValue = SequenceManager.this.nextValue(key, step) - step;
            sequenceValue = new AtomicLong(0);
        }

    }

    private static final Map<String, SequenceHolder> holder = new HashMap<>();

    /**
     * 获取下一个序列  确保唯一性
     *
     * @param identity Key
     * @return
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public long getNextSequence(String identity) {
        SequenceHolder sequenceHolder = holder.get(identity);
        if (sequenceHolder == null) {
            synchronized (holder) {
                sequenceHolder = holder.get(identity);
                if (sequenceHolder == null) {
                    sequenceHolder = new SequenceHolder(1);  // 默认为 1
                    sequenceHolder.setKey(identity);
                    sequenceHolder.init();
                    holder.put(identity, sequenceHolder);
                }
            }
        }
        return sequenceHolder.nextValue();
    }

    /**
     * 获取下一个序列  确保唯一性
     *
     * @param sequenceKey Key
     * @return
     */
    private long nextValue(String sequenceKey, long step) {
        for (int i = 0; i < 10; i++) {
            SequenceRecord sequenceRecord = sequenceRecordService.querySequence(sequenceKey);
            int effectRow = sequenceRecordService.nextValue(sequenceRecord.getSequenceValue() + step, sequenceRecord.getSequenceValue(), sequenceKey);
            if (effectRow == 1) {
                return sequenceRecord.getSequenceValue() + step;  // 返回下一个可用值
            }
        }
        throw new BizException(200, "获取序列失败");
    }
}
